﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.InteropServices;
using System.Windows.Forms;

namespace WindowsMessageAPI
{
    public class MessageHandler : System.Windows.Forms.NativeWindow, IDisposable
    {
        private bool disposed = false;

        #region Events
        public delegate void MessageRecieved(object sender, Message msg);

        public event MessageRecieved OnMessageReceived;

        public List<IntPtr> MessageFilters = new List<IntPtr>();

        #endregion

        #region WIN32 Declarations

        //API function to create custom system-wide Messages
        [DllImport("user32.dll")]
        public static extern IntPtr RegisterWindowMessage(String lpString);

        //API function to find window based on WindowName and class
        [DllImport("user32.dll")]
        public static extern IntPtr FindWindow(string lpClassName, string lpWindowName);

        //API function to send async. message to target application
        [DllImport("user32.dll")]
        public static extern IntPtr PostMessage(IntPtr hwnd, IntPtr wMsg, Int32 wParam, Int32 lParam);

        #endregion

        protected override void WndProc(ref Message m)
        {
            if (MessageFilters.Count > 0)
            {
                foreach (IntPtr filter in MessageFilters)
                {
                    if (m.Msg == filter.ToInt32())
                    {
                        OnMessageReceived(this, m);
                    }
                }
            }
            base.WndProc(ref m);
        }

        public void SendMessage(IntPtr windowID, IntPtr MessageID)
        {
            if (!System.IntPtr.Zero.Equals(windowID))
            {
                PostMessage(windowID, MessageID, 0, 0);
            }
        }

        public IntPtr GetHandle(string windowName)
        {
            return FindWindow(null, windowName);
        }

        public IntPtr RegisterMessage(string message)
        {
			return RegisterWindowMessage(message);
        }

        public MessageHandler(string globalName)
		{
			//Creating Window based on globally known name, and create handle
			//so we can start listening to Window Messages.
			CreateParams Params  = new CreateParams();
			Params.Caption = globalName;
			this.CreateHandle(Params);
		}
                
		public void Dispose()
		{
			Dispose(true);
			// This object will be cleaned up by the Dispose method.
			// Therefore, you should call GC.SupressFinalize to
			// take this object off the finalization queue 
			// and prevent finalization code for this object
			// from executing a second time.
			GC.SuppressFinalize(this);
		}
        
		private void Dispose(bool disposing)
		{
			// Check to see if Dispose has already been called.
			if(!this.disposed)
			{
				// If disposing equals true, dispose all managed 
				// and unmanaged resources.
				if(disposing)
				{

				}
             
				if (!this.Handle.Equals(IntPtr.Zero))
				{
					this.ReleaseHandle();
				}
			}
			disposed = true;         
		}
        
		~MessageHandler()
		{
			// Do not re-create Dispose clean-up code here.
			// Calling Dispose(false) is optimal in terms of
			// readability and maintainability.
			Dispose(false);
		}
    }
}
